home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Milan_1991 / Devcon91.4 / AppShell / Examples / Support / boundbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-01  |  12.6 KB  |  546 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/libraries.h>
  4. #include <intuition/intuition.h>
  5. #include <intuition/intuitionbase.h>
  6. #include <intuition/screens.h>
  7. #include <graphics/gfx.h>
  8. #include <graphics/text.h>
  9. #include <graphics/gfxmacros.h>
  10. #include <clib/macros.h>
  11. #include <clib/exec_protos.h>
  12. #include <clib/intuition_protos.h>
  13. #include <clib/graphics_protos.h>
  14.  
  15. void sprintf (void *,...);
  16.  
  17. #define    DEMO        FALSE
  18.  
  19. #define    PATTERN     TRUE
  20. #define    WINDOW        TRUE
  21. #define    MULTIDRAW    TRUE
  22.  
  23. #if MULTIDRAW
  24. #define    PolyDraw    MultiDraw
  25. #endif
  26.  
  27. #define    NUMPOINTS 5L
  28. #define    TOTPOINTS (NUMPOINTS * 2L)
  29. #define    SHIFTED (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  30.  
  31. struct Cursor
  32. {
  33.     struct Window *cs_Win;    /* Coordinate window */
  34.     struct TextFont *cs_Font;    /* Font to use */
  35.     ULONG cs_IDCMP;        /* Previous IDCMP settings */
  36.     ULONG cs_WinFlags;        /* Previous window flags */
  37.     UWORD cs_Points[TOTPOINTS];    /* Cursor point array */
  38.     UWORD cs_Pattern;        /* Pattern to use for cursor */
  39.  
  40.     /* These could easily be flags */
  41.     SHORT cs_Mode;        /* Drawing mode */
  42.     BOOL cs_Drag;        /* Dragging cursor? */
  43.     BOOL cs_Going;        /* Doing cursor? */
  44.     BOOL cs_Keyboard;        /* Done with mouse, now by key? */
  45.  
  46.     /* Text positioning information */
  47.     WORD cs_Left, cs_Line1, cs_Line2;
  48.  
  49.     BYTE cs_Buffer[8];        /* Coordinate buffer */
  50.     struct NewWindow cs_NW;    /* Our own NewWindow */
  51.     struct IBox cs_Box;        /* Cursor rectangle */
  52. };
  53.  
  54. /* dtcursor.c */
  55. VOID MultiDraw (struct RastPort *rp, LONG num, Point *xy);
  56. struct Cursor *AllocAnts (struct TextAttr * tattr);
  57. VOID FreeAnts (struct Cursor * cs);
  58. BOOL WhereIsMouse (struct IntuiMessage * msg, struct Cursor * cs);
  59. VOID AbortCut (struct Window * win, struct Cursor * cs);
  60. struct IBox *DoButtons (struct Window * win, struct IntuiMessage * msg, struct Cursor * cs);
  61. struct IBox *DoMouseMove (struct Window * win, struct IntuiMessage * msg, SHORT xadj, SHORT yadj, struct Cursor * cs);
  62. VOID AdjUpperLeft (SHORT xadj, SHORT yadj, struct Cursor * cs);
  63. VOID SetUpperLeft (struct IntuiMessage * msg, struct Cursor * cs);
  64. VOID AdjLowerRight (SHORT xadj, SHORT yadj, struct Cursor * cs);
  65. VOID SetLowerRight (struct IntuiMessage * msg, struct Cursor * cs);
  66. VOID ShowCoords (struct Window * win, struct Cursor * cs);
  67.  
  68. #define    WWIDTH    72
  69. #define    WHEIGHT    24
  70.  
  71. static struct NewWindow Coord =
  72. {
  73.     0, 0, WWIDTH, WHEIGHT,    /* Window dimensions */
  74.     0, 0,            /* No detail or block */
  75.     CLOSEWINDOW,        /* No IDCMP port */
  76.     BORDERLESS | NOCAREREFRESH | REPORTMOUSE,
  77.     NULL, NULL, NULL,
  78.     NULL,            /* Screen... */
  79.     NULL,
  80.     0, 0, 0, 0,
  81.     WBENCHSCREEN        /* For now... */
  82. };
  83.  
  84. static struct TextAttr TOPAZ80 =
  85. {(STRPTR) "topaz.font", TOPAZ_EIGHTY, 0, 0};
  86.  
  87. VOID MultiDraw (struct RastPort *rp, LONG num, Point *xy)
  88. {
  89.     register Point *coord = xy;
  90.     register LONG i, j = (num - 1);
  91.  
  92.     for (i = 0L; i < j; i++)
  93.     {
  94.         Move(rp, (LONG)coord->x, (LONG)coord->y);
  95.         coord++;
  96.         Draw(rp, (LONG)coord->x, (LONG)coord->y);
  97.     }
  98. }
  99.  
  100. struct Cursor *AllocAnts (struct TextAttr * tattr)
  101. {
  102.     extern struct Library *IntuitionBase;
  103.     struct Cursor *cs;
  104.  
  105.     /* Allocate our record */
  106.     if (cs = (struct Cursor *) AllocVec (sizeof (struct Cursor), MEMF_CLEAR))
  107.     {
  108.     register SHORT i;
  109.  
  110. #if WINDOW
  111.     /* We can only use the font if using 2.0 */
  112.     if (IntuitionBase->lib_Version >= 36)
  113.     {
  114.         struct TextAttr *attr = tattr;
  115.  
  116.         /* Copy the NewWindow from the template */
  117.         cs->cs_NW = *(&Coord);
  118.  
  119.         /* Did they provide a font? */
  120.         if (attr == NULL)
  121.         {
  122.         /* Use topaz 8 */
  123.         attr = &(TOPAZ80);
  124.         }
  125.  
  126.         /* Open the font */
  127.         if (cs->cs_Font = OpenFont (attr))
  128.         {
  129.         struct TextFont *f = cs->cs_Font;
  130.         struct RastPort rp;
  131.  
  132.         InitRastPort (&rp);
  133.         SetFont (&rp, f);
  134.  
  135.         /* Probably not the most intelligent way of getting the width,
  136.          * (especially when dealing with proportional fonts) ... */
  137.         cs->cs_NW.Width = TextLength (&rp, " 999,999 ", 9) + 2;
  138.         cs->cs_NW.Height = (f->tf_YSize * 2) + 5;
  139.  
  140.         cs->cs_Left = TextLength (&rp, " ", 1);
  141.         cs->cs_Line1 = 2 + f->tf_Baseline;
  142.         cs->cs_Line2 = 1 + f->tf_YSize + cs->cs_Line1;
  143.         }
  144.     }
  145. #endif
  146.  
  147.     /* Initialize the record */
  148. #if PATTERN
  149.     cs->cs_Pattern = 0xF0F0;
  150. #else
  151.     cs->cs_Pattern = 0xFFFF;
  152. #endif
  153.     cs->cs_Drag = FALSE;
  154.     cs->cs_Going = FALSE;
  155.     cs->cs_Keyboard = FALSE;
  156.     cs->cs_Mode = 0;
  157.  
  158.     /* Clear the array */
  159.     for (i = 0; i < TOTPOINTS; i++)
  160.     {
  161.         cs->cs_Points[i] = 0;
  162.     }
  163.  
  164.     /* Clear the box */
  165.     cs->cs_Box.Left = 0;
  166.     cs->cs_Box.Top = 0;
  167.     cs->cs_Box.Width = 0;
  168.     cs->cs_Box.Height = 0;
  169.     }
  170.  
  171.     return (cs);
  172. }
  173.  
  174. VOID FreeAnts (struct Cursor * cs)
  175. {
  176.  
  177.     /* Make sure we have a record */
  178.     if (cs)
  179.     {
  180.     if (cs->cs_Win)
  181.     {
  182.         CloseWindow (cs->cs_Win);
  183.         cs->cs_Win = NULL;
  184.     }
  185.  
  186.     /* Font open? */
  187.     if (cs->cs_Font)
  188.     {
  189.         /* Close the font */
  190.         CloseFont (cs->cs_Font);
  191.     }
  192.  
  193.     /* Free the record */
  194.     FreeVec (cs);
  195.     }
  196. }
  197.  
  198. VOID
  199. ShowCoords (struct Window * win, struct Cursor * cs)
  200. {
  201.  
  202.     if (win)
  203.     {
  204.     struct IBox *box = &(cs->cs_Box);
  205.     struct Screen *scr = win->WScreen;
  206.     struct IntuiMessage *msg;
  207.  
  208.     /* Move the little window around */
  209.     ChangeWindowBox (win,
  210.              (scr->MouseX + 10), (scr->MouseY - win->Height),
  211.              win->Width, win->Height);
  212.  
  213.     /* Print the width & height */
  214.     sprintf (cs->cs_Buffer, "%3d,%3d", box->Width, box->Height);
  215.     Move (win->RPort, cs->cs_Left, cs->cs_Line2);
  216.     Text (win->RPort, cs->cs_Buffer, 7);
  217.  
  218.     /* Clear out any outstanding messages. */
  219.     while (msg = (struct IntuiMessage *) GetMsg (win->UserPort))
  220.     {
  221.         ReplyMsg ((struct Message *) msg);
  222.     }
  223.     }
  224. }
  225.  
  226. VOID AbortCut (struct Window * win, struct Cursor * cs)
  227. {
  228.     /* Is the cursor active? */
  229.     if (cs->cs_Going)
  230.     {
  231.     struct RastPort crp = *win->RPort;
  232.  
  233.     /* No mask... */
  234.     crp.Mask = ~0;
  235.  
  236.     SetDrMd (&crp, COMPLEMENT);
  237.     SetDrPt (&crp, cs->cs_Pattern);
  238.     Move (&crp, cs->cs_Points[0], cs->cs_Points[1]);
  239.     PolyDraw (&crp, NUMPOINTS, (Point *)&(cs->cs_Points[0]));
  240.     }
  241.  
  242.     /* Is the coordinate window open? */
  243.     if (cs->cs_Win)
  244.     {
  245.     /* Close it */
  246.     CloseWindow (cs->cs_Win);
  247.     cs->cs_Win = NULL;
  248.     }
  249.  
  250.     /* Clear stuff */
  251.     cs->cs_Drag = cs->cs_Keyboard = cs->cs_Going = FALSE;
  252.     cs->cs_Mode = 0;
  253. }
  254.  
  255. VOID BoundCheckMouse (struct IntuiMessage * msg, struct Cursor * cs)
  256. {
  257.     struct Window *win = msg->IDCMPWindow;
  258.  
  259.     /* Freshen the values */
  260.     msg->MouseX = win->MouseX;
  261.     msg->MouseY = win->MouseY;
  262.  
  263.     /* Make sure mouse is in the window */
  264.     {
  265.     WORD tx = win->BorderLeft;
  266.     WORD ty = win->BorderTop;
  267.     WORD bx = win->Width - win->BorderRight - 1;
  268.     WORD by = win->Height - win->BorderBottom - 1;
  269.  
  270.     /* Range check the horizontal value */
  271.     if (msg->MouseX < tx)
  272.         msg->MouseX = tx;
  273.     else if (msg->MouseX > bx)
  274.         msg->MouseX = bx;
  275.  
  276.     /* Range check the vertical value */
  277.     if (msg->MouseY < ty)
  278.         msg->MouseY = ty;
  279.     else if (msg->MouseY > by)
  280.         msg->MouseY = by;
  281.     }
  282. }
  283.  
  284. VOID UpdateBox (struct Cursor * cs)
  285. {
  286.  
  287.     /* Revise the box */
  288.     cs->cs_Box.Left = MIN (cs->cs_Points[0], cs->cs_Points[4]);
  289.     cs->cs_Box.Top = MIN (cs->cs_Points[1], cs->cs_Points[5]);
  290.     cs->cs_Box.Width = MAX (cs->cs_Points[0], cs->cs_Points[4]);
  291.     cs->cs_Box.Height = MAX (cs->cs_Points[1], cs->cs_Points[5]);
  292.     cs->cs_Box.Width = cs->cs_Box.Width - cs->cs_Box.Left + 1;
  293.     cs->cs_Box.Height = cs->cs_Box.Height - cs->cs_Box.Top + 1;
  294. }
  295.  
  296. struct IBox *
  297. DoButtons (struct Window * win, struct IntuiMessage * msg, struct Cursor * cs)
  298. {
  299.     /* Freshen & revise the coordinates */
  300.     BoundCheckMouse (msg, cs);
  301.  
  302.     switch (msg->Code)
  303.     {
  304.     case SELECTDOWN:
  305.  
  306.         /* See if the cursor is already active */
  307.         if (cs->cs_Going)
  308.         {
  309.         /* Turn it off */
  310.         AbortCut (win, cs);
  311.         }
  312.  
  313.         /* Set coordinates */
  314.         SetUpperLeft (msg, cs);
  315.         SetLowerRight (msg, cs);
  316.  
  317.         /* Revise the box */
  318.         UpdateBox (cs);
  319.  
  320.         /* Draw the first frame */
  321.         {
  322.         struct RastPort crp = *win->RPort;
  323.  
  324.         /* No mask... */
  325.         crp.Mask = ~0;
  326.  
  327.         SetDrMd (&crp, COMPLEMENT);
  328.         Move (&crp, cs->cs_Points[0], cs->cs_Points[1]);
  329.         PolyDraw (&crp, NUMPOINTS, (Point *)&(cs->cs_Points[0]));
  330.         }
  331.  
  332.         /* Set some pertinant values */
  333.         cs->cs_Drag = TRUE;
  334.         cs->cs_Going = TRUE;
  335.         cs->cs_Keyboard = FALSE;
  336.         cs->cs_Mode = 1;
  337.  
  338.         /* Do we need to do a coordinate window? */
  339.         if ((cs->cs_Win == NULL) && cs->cs_Font)
  340.         {
  341.         struct Screen *scr = win->WScreen;
  342.         struct IBox *box = &(cs->cs_Box);
  343.  
  344.         /* Adjust the upper-left */
  345.         cs->cs_NW.LeftEdge = (scr->MouseX + 10);
  346.         cs->cs_NW.TopEdge = (scr->MouseY - cs->cs_NW.Height);
  347.         cs->cs_NW.Type = CUSTOMSCREEN;
  348.         cs->cs_NW.Screen = scr;
  349.  
  350.         if (cs->cs_Win = OpenWindowTags (&(cs->cs_NW),
  351.                          WA_AutoAdjust, TRUE,
  352.                          TAG_DONE))
  353.         {
  354.             /* Clear the area */
  355.             SetRast (cs->cs_Win->RPort, 1);
  356.             SetAPen (cs->cs_Win->RPort, 2);
  357.             RectFill (cs->cs_Win->RPort,
  358.              1, 1, (cs->cs_Win->Width - 2), (cs->cs_Win->Height - 2));
  359.  
  360.             /* Make it readable */
  361.             SetAPen (cs->cs_Win->RPort, 1);
  362.             SetBPen (cs->cs_Win->RPort, 2);
  363.             SetDrMd (cs->cs_Win->RPort, JAM2);
  364.             SetFont (cs->cs_Win->RPort, cs->cs_Font);
  365.  
  366.             /* Print the upper-left coordinates */
  367.             sprintf (cs->cs_Buffer, "%3d,%3d",
  368.                  (box->Left - win->BorderLeft),
  369.                  (box->Top - win->BorderTop));
  370.             Move (cs->cs_Win->RPort, cs->cs_Left, cs->cs_Line1);
  371.             Text (cs->cs_Win->RPort, cs->cs_Buffer, 7);
  372.         }
  373.         }
  374.  
  375.         /* Show the coordinates */
  376.         ShowCoords (cs->cs_Win, cs);
  377.  
  378.         /* Save & modify the window flags */
  379.         cs->cs_IDCMP = win->IDCMPFlags;
  380.         cs->cs_WinFlags = win->Flags;
  381.         win->Flags |= RMBTRAP;
  382.         break;
  383.  
  384.     case MENUDOWN:
  385.         /* See if the cursor is already active */
  386.         if (cs->cs_Going)
  387.         {
  388.         /* Turn it off */
  389.         AbortCut (win, cs);
  390.         }
  391.  
  392.         /* Restore the window flags */
  393.         if (!(cs->cs_WinFlags & RMBTRAP))
  394.         {
  395.         win->Flags &= ~RMBTRAP;
  396.         }
  397.         break;
  398.  
  399.     case SELECTUP:
  400.         /* set the bounding box rectangle if we where doing bounds */
  401.         if (cs->cs_Mode == 1)
  402.         {
  403.         /* Revise the box */
  404.         UpdateBox (cs);
  405.         }
  406.  
  407.         /* Clear some values */
  408.         cs->cs_Drag = FALSE;
  409.         cs->cs_Keyboard = TRUE;
  410.         cs->cs_Mode = 2;
  411.  
  412.         /* Restore the window flags */
  413.         if (!(cs->cs_WinFlags & RMBTRAP))
  414.         {
  415.         win->Flags &= ~RMBTRAP;
  416.         }
  417.  
  418.         if (cs->cs_Win)
  419.         {
  420.         CloseWindow (cs->cs_Win);
  421.         cs->cs_Win = NULL;
  422.         }
  423.  
  424.  
  425.         break;
  426.     }
  427.  
  428.     return (&(cs->cs_Box));
  429. }
  430.  
  431. struct IBox *
  432. DoMouseMove (struct Window * win, struct IntuiMessage * msg,
  433.            SHORT xadj, SHORT yadj, struct Cursor * cs)
  434. {
  435. #if PATTERN
  436.     if (cs->cs_Going)
  437. #else
  438.     if (cs->cs_Drag)
  439. #endif
  440.     {
  441.     struct RastPort crp;
  442.     USHORT dir;
  443.  
  444.     /* Copy the RastPort */
  445.     crp = *(win->RPort);
  446.     crp.Mask = ~0;
  447.  
  448.     /* Check the mouse coordinates */
  449.     BoundCheckMouse (msg, cs);
  450.  
  451.     /* Erase the prior image */
  452.     SetDrMd (&crp, COMPLEMENT);
  453.     SetDrPt (&crp, cs->cs_Pattern);
  454.     Move (&crp, cs->cs_Points[0], cs->cs_Points[1]);
  455.     PolyDraw (&crp, NUMPOINTS, (Point *)&(cs->cs_Points[0]));
  456.  
  457. #if PATTERN
  458.     /* Get the direction that we're traveling */
  459.     dir = ((cs->cs_Points[0] < cs->cs_Points[2]) ||
  460.            (cs->cs_Points[1] > cs->cs_Points[5])) ? 0 : 1;
  461.  
  462.     /* Adjust the ants according to direction */
  463.     if (dir)
  464.     {
  465.         cs->cs_Pattern = ((cs->cs_Pattern << 1) & 0xfffe) |
  466.           ((cs->cs_Pattern & 0x8000) >> 15);
  467.     }
  468.     else
  469.     {
  470.         cs->cs_Pattern = ((cs->cs_Pattern >> 1) & 0x7fff) |
  471.           ((cs->cs_Pattern & 1) << 15);
  472.     }
  473. #endif
  474.  
  475.     if ((xadj && yadj) || cs->cs_Keyboard)
  476.     {
  477.         if (msg->Qualifier & SHIFTED)
  478.         AdjLowerRight (xadj, yadj, cs);
  479.         else
  480.         AdjUpperLeft (xadj, yadj, cs);
  481.     }
  482.     else
  483.     {
  484.         SetLowerRight (msg, cs);
  485.     }
  486.  
  487.     /* Draw the new ants */
  488.     SetDrPt (&crp, cs->cs_Pattern);
  489.     Move (&crp, cs->cs_Points[0], cs->cs_Points[1]);
  490.     PolyDraw (&crp, NUMPOINTS, (Point *)&(cs->cs_Points[0]));
  491.  
  492.     /* Update the box */
  493.     if (cs->cs_Mode == 1)
  494.     {
  495.         /* Revise the box */
  496.         UpdateBox (cs);
  497.     }
  498.     }
  499.  
  500.     if (cs->cs_Drag)
  501.     {
  502.     ShowCoords (cs->cs_Win, cs);
  503.     }
  504.  
  505.     return (&(cs->cs_Box));
  506. }
  507.  
  508. VOID AdjUpperLeft (SHORT xadj, SHORT yadj, struct Cursor * cs)
  509. {
  510.  
  511.     cs->cs_Points[0] += xadj;
  512.     cs->cs_Points[6] = cs->cs_Points[8] = cs->cs_Points[0];
  513.  
  514.     cs->cs_Points[1] += yadj;
  515.     cs->cs_Points[3] = cs->cs_Points[9] = cs->cs_Points[1];
  516. }
  517.  
  518. VOID SetUpperLeft (struct IntuiMessage * msg, struct Cursor * cs)
  519. {
  520.  
  521.     cs->cs_Points[0] = cs->cs_Points[2] = msg->MouseX;
  522.     cs->cs_Points[4] = cs->cs_Points[6] = msg->MouseX;
  523.     cs->cs_Points[8] = msg->MouseX;
  524.  
  525.     cs->cs_Points[1] = cs->cs_Points[3] = msg->MouseY;
  526.     cs->cs_Points[5] = cs->cs_Points[7] = msg->MouseY;
  527.     cs->cs_Points[9] = msg->MouseY;
  528. }
  529.  
  530. VOID AdjLowerRight (SHORT xadj, SHORT yadj, struct Cursor * cs)
  531. {
  532.  
  533.     cs->cs_Points[2] += xadj;
  534.     cs->cs_Points[4] = cs->cs_Points[2];
  535.  
  536.     cs->cs_Points[5] += yadj;
  537.     cs->cs_Points[7] = cs->cs_Points[5];
  538. }
  539.  
  540. VOID SetLowerRight (struct IntuiMessage * msg, struct Cursor * cs)
  541. {
  542.  
  543.     cs->cs_Points[2] = cs->cs_Points[4] = msg->MouseX;
  544.     cs->cs_Points[5] = cs->cs_Points[7] = msg->MouseY;
  545. }
  546.